﻿namespace Leetcode.N0010;
public class Solution
{
    public bool IsMatch(string s, string p)
    {
        return this.IsMatch(s, 0, p, 0);
    }

    private bool IsMatch(string s, int sStartIndex, string p, int pStartIndex)
    {
        if (pStartIndex >= p.Length)
        {
            if (sStartIndex >= s.Length)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        var pEndIndex = this.GetNextTokenEndIndex(p, pStartIndex);

        if (sStartIndex >= s.Length)
        {
            if (p[pEndIndex] == '*')
            {
                return this.IsMatch(s, sStartIndex, p, pEndIndex + 1);
            }
            return false;
        }

        if (p[pEndIndex] == '*')
        {
            var sEndIndex = this.GetMathEndIndex(s, sStartIndex, p[pEndIndex - 1]);
            if (sEndIndex == -1)
            {
                return this.IsMatch(s, sStartIndex, p, pEndIndex + 1);
            }
            else
            {
                for (int sIndex = sStartIndex; sIndex <= sEndIndex + 1; sIndex++)
                {
                    var result = this.IsMatch(s, sIndex, p, pEndIndex + 1);
                    if (result)
                    {
                        return true;
                    }
                }
                return false;
            }

        }
        else
        {
            if (this.IsMatchFixString(s, sStartIndex, p, pStartIndex, pEndIndex))
            {
                return this.IsMatch(s, sStartIndex + (pEndIndex - pStartIndex + 1), p, pEndIndex + 1);
            }
            else
            {
                return false;
            }
        }
    }

    private bool IsMatchFixString(string s, int startIndex, string p, int pStartIndex, int pEndIndex)
    {

        for (int pIndex = pStartIndex; pIndex <= pEndIndex; pIndex++)
        {
            var sIndex = startIndex + (pIndex - pStartIndex);
            if (sIndex >= s.Length)
            {
                return false;
            }
            if (p[pIndex] != s[sIndex] && p[pIndex] != '.')
            {
                return false;
            }
        }
        return true;
    }

    private int GetMathEndIndex(string s, int sStartIndex, char p)
    {
        if (p == '.')
        {
            return s.Length - 1; ;
        }

        var endIndex = -1;
        for (int i = sStartIndex; i < s.Length; i++)
        {
            if (s[i] != p)
            {
                break;
            }
            endIndex = i;
        }


        return endIndex;
    }

    private int GetNextTokenEndIndex(string p, int startIndex)
    {
        for (int i = startIndex; i < p.Length; i++)
        {
            if (i < p.Length - 1)
            {
                if (p[i + 1] == '*')
                {
                    if (i == startIndex)
                    {
                        return i + 1;
                    }
                    else
                    {
                        return i - 1;
                    }
                }
            }
            else
            {
                return i;
            }
        }
        return p.Length - 1;
    }

}
